include ../_util-fns

:marked
  ## Setup to develop locally
  
  ## 为本地开发搭建环境
  
  Follow the [setup](../guide/setup.html) instructions for creating a new project
  named <code>angular-tour-of-heroes</code>.
  
  根据[开发环境](../guide/setup.html)中的说明创建一个名为<ngio-ex path="angular-tour-of-heroes"></ngio-ex>的新项目

  The file structure should look like this:

  该项目的文件结构应该是这样的：

.filetree
  .file angular-tour-of-heroes
  .children
    .file src
    .children
      .file app
      .children
        .file app.component.ts
        .file app.module.ts
      .file main.ts
      .file index.html
      .file styles.css
      .file systemjs.config.js
      .file tsconfig.json
    .file node_modules ...
    .file package.json
:marked
  When you're done with this page, the app should look like this <live-example></live-example>.

  在我们完成本章时，得到的应用和这个<live-example></live-example>一样。

a#keep-transpiling
:marked
  ## Keep the app transpiling and running
  
  ## 保持应用不断转译和运行
  
  Enter the following command in the terminal window:
  
  在命令行窗口中输入以下命令：

code-example(language="sh" class="code-shell").
  npm start

:marked
  This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes.
  The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
  
  这个命令会在“监听”模式下运行TypeScript编译器，当代码变化时，它会自动重新编译。
  同时，该命令还会在浏览器中启动该应用，并且当代码变化时刷新浏览器。

  You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.

  在后续构建《英雄指南》过程中，应用能持续运行，而不用中断服务来编译或刷新浏览器。

.l-main-section
  :marked
    ## Show the hero
    
    ## 显示此英雄
    
    Add two properties to the `AppComponent`: a `title` property for the app name and a `hero` property
    for a hero named "Windstorm."
    
    往`AppComponent`中添加两个属性：`title`属性用来表示应用的名字，而`hero`属性用来表示名叫“Windstorm”的英雄。

  +makeExample('toh-1/ts/app/app.component.1.ts', 'app-component-1', 'app.component.ts (AppComponent class)')(format=".")

  :marked
    Now update the template in the `@Component` decorator with data bindings to these new properties.

    下面，更新`@Component`装饰器中指定的模板，为这些新属性建立数据绑定。

  +makeExample('toh-1/ts/app/app.component.1.ts', 'show-hero',  'app.component.ts (@Component)')(format='.')

  :marked
    The browser refreshes and displays the title and hero name.
    
    保存后，浏览器应自动刷新，显示标题和英雄。

    The double curly braces are Angular's *interpolation binding* syntax.
    These interpolation bindings present the component's `title` and `hero` property values,
    as strings, inside the HTML header tags.
    
    这里的双大括号是Angular中的*插值表达式绑定*语法。它们表示组件的`title`和`hero`属性的值会作为字符串插入到HTML标签中间。

.l-sub-section
  :marked
    Read more about interpolation in the [Displaying Data](../guide/displaying-data.html) page.
    
    要了解插值表达式的更多知识，见[显示数据](../guide/displaying-data.html)。

:marked
  ### Hero object
  
  ### Hero 对象

  The hero needs more properties.
  Convert the `hero` from a literal string to a class.

  显然，英雄还需要更多属性。
  让我们把`hero`从一个字符串字面量换成一个类。

  Create a `Hero` class with `id` and `name` properties.
  Add these properties near the top of the `app.component.ts` file, just below the import statement.

  创建一个`Hero`类，它具有`id`和`name`属性。
  现在，把下列代码放在`app.component.ts`的顶部，仅次于 import 语句。

+makeExample('toh-1/ts/src/app/app.component.ts', 'hero-class-1', 'src/app/app.component.ts (Hero class)')(format=".")

:marked
  In the `AppComponent` class, refactor the component's `hero` property to be of type `Hero`,
  then initialize it with an `id` of `1` and the name `Windstorm`.

  现在，有了一个`Hero`类，我们把组件`hero`属性的类型换成`Hero`。
  然后以`1`为 id、以 “Windstorm” 为名字，初始化它。

+makeExample('toh-1/ts/src/app/app.component.ts', 'hero-property-1', 'src/app/app.component.ts (hero property)')(format=".")

:marked
  Because you changed the hero from a string to an object,
  update the binding in the template to refer to the hero's `name` property.

  我们把`hero`从一个字符串换成了对象，所以也得更新模板中的绑定表达式，来引用`hero`的`name`属性。

+makeExample('toh-1/ts/app/app.component.1.ts', 'show-hero-2')
:marked
  The browser refreshes and continues to display the hero's name.
  
  浏览器自动刷新，并继续显示这位英雄的名字。

  ### Adding HTML with multi-line template strings
  
  ### 使用多行模板字符串添加更多 HTML

  To show all of the hero's properties,
  add a `<div>` for the hero's `id` property and another `<div>` for the hero's `name`.
  To keep the template readable, place each `<div>` on its own line.
  
  要显示英雄的所有属性，还要为英雄的`id`属性添加一个`<div>`，为英雄的`name`属性添加另一个`<div>`。
  为了保持模板的可读性，把每个`<div>`单独放一行。

  The backticks around the component template let you put the `<h1>`, `<h2>`, and `<div>` elements on their own lines,
  thanks to the <i>template literals</i> feature in ES2015 and TypeScript. For more information, see
  <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" target="_blank" title="template literal">Template literals</a>.
  
  反引号包裹的组件模板能让你把`<h1>`、`<h2>`和`<div>`元素各自放在一行上。
  感谢ES2015和TypeScript的*模板字面量*特性。要了解更多，请参见<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" target="_blank" title="template literal">模板字面量（Template literals）</a> 页。


+makeExample('toh-1/ts/app/app.component.1.ts', 'multi-line-strings', 'app.component.ts (AppComponent\'s template)')(format='.')

.l-main-section
:marked
  ## Edit the hero name
  
  ## 编辑英雄名字

  Users should be able to edit the hero name in an `<input>` textbox.
  The textbox should both _display_ the hero's `name` property
  and _update_ that property as the user types.
  
  用户应该能在一个`<input>`输入框中编辑英雄的名字。
  当用户输入时，这个输入框应该能同时*显示*和*修改*英雄的`name`属性。

  You need a two-way binding between the `<input>` form element and the `hero.name` property.
  
  也就是说，我们要在表单元素`<input>`和组件的`hero.name`属性之间建立双向绑定。

  ### Two-way binding
  
  ### 双向绑定

  Refactor the hero name in the template so it looks like this:
  
  把模板中的英雄名字重构成这样：
  
+makeExample('toh-1/ts/app/app.component.1.ts', 'name-input')(format='.')

:marked
  `[(ngModel)]` is the Angular syntax to bind the `hero.name` property
  to the textbox.
  Data flows _in both directions:_ from the property to the textbox,
  and from the textbox back to the property.
  
  `[(ngModel)]`是一个Angular语法，用与把`hero.name`绑定到输入框中。
  它的数据流是*双向的*：从属性到输入框，并且从输入框回到属性。

  Unfortunately, immediately after this change, the application breaks.
  If you looked in the browser console, you'd see Angular complaining that
  "`ngModel` ... isn't a known property of `input`."
  
  不幸的是，做了这项改动之后，我们的程序崩溃了。
  打开浏览器的控制台，我们会看到Angular抱怨说：“`ngModel` ... isn't a known property of `input`.”（`ngModel`不是`input`元素的已知属性）

  Although `NgModel` is a valid Angular directive, it isn't available by default.
  It belongs to the optional `FormsModule`.
  You must opt-in to using that module.
  
  虽然`NgModel`是一个有效的Angular指令，但它默认情况下却是不可用的。
  它属于一个可选模块`FormsModule`。
  我们必须选择使用那个模块。

  ### Import the _FormsModule_
  
  ### 导入 _FormsModule_

  Open the `app.module.ts` file and import the `FormsModule` symbol from the `@angular/forms` library.
  Then add the `FormsModule` to the `@NgModule` metadata's `imports` array, which contains the list
  of external modules that the app uses.
  
  打开`app.module.ts`文件，并且从`@angular/forms`库中导入符号`FormsModule`。
  然后把`FormsModule`添加到`@NgModule`元数据的`imports`数组中，它是当前应用正在使用的外部模块列表。

  The updated `AppModule` looks like this:
  
  修改后的`AppModule`是这样的：
  
+makeExample('toh-1/ts/src/app/app.module.ts', '', 'app.module.ts (FormsModule import)')

.l-sub-section
  :marked
    Read more about `FormsModule` and `ngModel` in the
    [Two-way data binding with ngModel](../guide/forms.html#ngModel) section of the
    [Forms](../guide/forms.html) guide and the
    [Two-way binding with NgModel](../guide/template-syntax.html#ngModel) section of the
    [Template Syntax](../guide/template-syntax.html) guide.

    要学习关于`FormsModule`和`ngModel`的更多知识，参见[表单](../guide/forms.html#ngModel)和
    [模板语法](../guide/template-syntax.html#ngModel)。

:marked
  When the browser refreshes, the app should work again.
  You can edit the hero's name and see the changes reflected immediately in the `<h2>` above the textbox.

  浏览器刷新。又见到我们的英雄了。我们可以编辑英雄的名字，也能看到这个改动立刻体现在`<h2>`中。

.l-main-section
:marked
  ## The road you've travelled
  
  ## 我们已经走过的路
  
  Take stock of what you've built.
  
  我们来盘点一下已经构建完成的部分。

  * The Tour of Heroes app uses the double curly braces of interpolation (a type of one-way data binding)
  to display the app title and properties of a `Hero` object.
  
    我们的《英雄指南》使用双大括号插值表达式(单向数据绑定的一种形式)来显示应用的标题和`Hero`对象的属性。
    
  * You wrote a multi-line template using ES2015's template literals to make the template readable.
  
    我们使用 ES2015 的模板字符串写了一个多行模板，使我们的模板更具可读性。
    
  * You added a two-way data binding to the `<input>` element
  using the built-in `ngModel` directive. This binding both displays the hero's name and allows users to change it.
  
    为了同时显示和修改英雄的名字，我们还使用了内置的`ngModel`指令，往`<input>`元素上添加了双向数据绑定。
    
  * The `ngModel` directive propagates changes to every other binding of the `hero.name`.
  
    `ngModel`指令将这些修改传播到每一个对`hero.name`的其它绑定。

  Your app should look like this <live-example></live-example>.

  运行这部分的<live-example></live-example>。

  Here's the complete `app.component.ts` as it stands now:

  完整的`app.component.ts`是这样的：

+makeExample('toh-1/ts/src/app/app.component.ts', '', 'src/app/app.component.ts')

.l-main-section
:marked
  ## The road ahead
  
  ## 前方的路
  
  In the [next tutorial page](./toh-pt2.html), you'll build on the Tour of Heroes app to display a list of heroes.
  You'll also allow the user to select heroes and display their details.
  You'll learn more about how to retrieve lists and bind them to the template.

  在[教程的下一章](./toh-pt2.html)，我们将在这个《英雄指南》中显示一个英雄列表。
  我们将允许允许用户选择一个英雄，并且显示它/她的详情。
  我们还将学会如何获取列表以及将它们绑定到模板中。
